import random
  
class P4:

  # requiert deux algorithmes ainsi que la largeur et la longueur de la matrice
  def __init__(self,j1,j2,L,l):
  
    self.m=self.__matrice([],L,l)
    self.mp=(L,l)
    
    # ordre aleatoire des joueurs, s'inverse tour par tour
    self.ordre=random.sample([[j1,1],[j2,2]],k=2)

    # ordonne si le programme doit fonctionner
    self.sig=True
    
    # etats du jeu : Nouveau Joueur, Pion Joueur, Verification Pion, Changement Joueur
    self.stock=["NJ","PJ","VP","CJ"]

    # etats pouvant etre acceder par l'utilisateur
    self.state=[self.stock[0],(),"J"+str(self.ordre[0][1])]
    
    # le match est fini ou non, avec le potentiel vainqueur
    self.match=[True,""]
    
  # coeur du programme a mettre a jour
  def update(self):
  
    # lance seulement si le match n'est pas termine et que la pause n'est pas active
    if self.sig and self.match[0]:
    
      if self.stock[0]=="CJ":
        self.__inverse()
        
        # informe un nouveau joueur
        self.state[2]="J"+str(self.ordre[0][1])
        
      elif self.stock[0]=="PJ":
        self.__placer()
        
      elif self.stock[0]=="VP":
        self.__detection()

      # comportement similaire a une file pour self.stock, sauf que les elements ne s'enlevent jamais
      self.state[0]=self.stock[0]
      self.stock.append(self.stock.pop(0))
      
    else:
      pass
  
  """ Fonctions utilitaires """
     
  def get_state(self):
    return self.state[0],self.state[1],self.state[2]
    
  def get_match(self):
    return self.match[0],self.match[1]
  
  def get_matrice(self):
    return self.m
  
  def pause(self,arg):
    self.sig=arg
    
  """ Fonctions privees, elles ne peuvent pas etre accede """
  
  # place le pion en fonction des pieces existantes, puis, renvoit ses coordonnees
  def __placer(self):
  
    a=0
    x=self.ordre[0][0](self.m,self.ordre[0][1])
    
    # remet a la derniere colonne si x est trop grand
    if x>=self.mp[1]:
    
      x=self.mp[1]-1
      
    for i in range(self.mp[0]):

      # la piece tombe tant qu'elle ne rencontre rien
      if self.m[i][x]==0:
        a+=1
        
      else:
        break
    
    # regle un probleme avec a=0
    if self.m[a-1][x]!=0 and a==0:
    
      pass
      
    else:
      self.m[a-1][x],self.state[1]=self.ordre[0][1],(a-1,x)
  
  # inverse l'ordre des joueurs
  def __inverse(self):
  
    self.ordre[0],self.ordre[1]=self.ordre[1],self.ordre[0]
    
  # creer une matrice
  def __matrice(self,m,y,x):
  
    for i in range(y):
        m.append([])
        
        for j in range(x):
            m[i].append(0)
    return m
    
  def __detection(self):
  
    """ Detection en ligne """
    
    ligne=[]
    ligne_str=""
    
    for ele in self.m[self.state[1][0]]:
        ligne.append(str(ele))
        
    # transformation de la liste en str pour une utilisation optimale
    ligne_str=ligne_str.join(ligne)
    
    if "1111" in ligne_str:
        self.match[1]="J1"
        self.match[0]=False
        
    if "2222" in ligne_str:
        self.match[1]="J2"
        self.match[0]=False
        
    """ Detection en colonne """
    
    colonne=[]
    
    # boucle recuperant la colonne du pion
    for ele in self.m:
    
        colonne.append(str(ele[self.state[1][1]]))
    colonne_str=""
    
    # transformation de la liste en str pour une utilisation optimale
    colonne_str=colonne_str.join(colonne)
    
    if "1111" in colonne_str:
        self.match[1]="J1"
        self.match[0]=False
        
    if "2222" in colonne_str:
        self.match[1]="J2"
        self.match[0]=False
        
    """ Detection en diagonale de gauche a droite puis de droite a gauche """
    
    f=[lambda x: x+1,lambda x: x-1]
    ac=[(1,1),(0,0),(0,1),(1,0)]
    
    # compteur incrementer pour chaque pion successif du joueur sur la diagonale
    cpt=0
    
    for o in range(4):
    
      i=self.state[1][0]
      j=self.state[1][1]
      
      # parcourt
      while i>=0 and j>=0 and i<self.mp[0] and j<self.mp[1]:
      
        if self.m[i][j]!=self.m[self.state[1][0]][self.state[1][1]]:
          break
        cpt=cpt+1
        i=f[ac[o][0]](i)
        j=f[ac[o][1]](j)
        
      if o==1:
        cpt=0

      if cpt>=5:
        self.match[1]="J"+str(self.m[self.state[1][0]][self.state[1][1]])
        self.match[0]=False
        break
        
    """ Detection egalite """
    
    if self.match[0]:
      cpt=0
      
      for i in range(self.mp[1]):
          lig=0
          
          if self.m[0][i]!=0:
                cpt=cpt+1
                
      if cpt>=self.mp[1]:
          self.match[1]="EGALITE"
          self.match[0]=False